package org.vacoor.nothing.ui.util;

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * 剪切板, 主要包括两部分, 系统剪切板/应用剪切板
 * <p/>
 * 系统剪切板: 与 OS 交互, 主要存取 文本,图像
 * <pre>
 *     Clipboards.setSysClipboardText("这个是系统寄存器");
 *     String text = Clipboards.getSysClipboardText();
 *     System.out.println(text);
 * </pre>
 * 应用剪切板: JVM 内部，可以存取任意对象
 * <pre>
 *     Clipboards.setAppClipboardObject(new File("heh.jpg"));
 *     File file = (File) Clipboards.getAppClipboardObject();
 *     System.out.println(file.getCanonicalPath());
 * </pre>
 *
 * @author Vacoor
 */
public abstract class Clipboards {
    private static final Clipboard sysClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    private static Clipboard appClipboard;

    /**
     * 设置系统剪切板文本内容
     *
     * @param data
     */
    public static void setSysClipboardText(String data) {
        sysClipboard.setContents(new StringSelection(data), null);
    }

    /**
     * 获取系统剪切板文本内容
     *
     * @return
     */
    public static String getSysClipboardText() {
        return (String) getDataFromClipboard(sysClipboard, DataFlavor.stringFlavor);
    }

    /**
     * 设置系统剪切板图像内容
     *
     * @param image
     */
    public static void setSysClipboardImage(Image image) {
        setImageToClipboard(sysClipboard, image);
    }

    /**
     * 获取系统剪切板图像
     *
     * @return
     */
    public static BufferedImage getSysClipboardImage() {
        return (BufferedImage) getDataFromClipboard(sysClipboard, DataFlavor.imageFlavor);
    }

    // ---------- JVM 内剪切板, 可以存放对象 -----

    /**
     * 设置应用剪切板文本
     *
     * @param data
     */
    public static void setAppClipboardText(String data) {
        ensureAppClipboard();
        appClipboard.setContents(new StringSelection(data), null);
    }

    /**
     * 获取应用剪切板文本
     *
     * @return
     */
    public static String getAppClipboardText() {
        return (String) getDataFromClipboard(appClipboard, DataFlavor.stringFlavor);
    }

    /**
     * 设置应用剪切板图像
     *
     * @param image
     */
    public static void setAppClipboardImage(Image image) {
        ensureAppClipboard();
        setImageToClipboard(appClipboard, image);
    }

    /**
     * 获取应用剪切板图像
     *
     * @return
     */
    public static Image getAppClipboardImage() {
        return (Image) getDataFromClipboard(appClipboard, DataFlavor.imageFlavor);
    }

    /**
     * 设置对象到应用剪切板
     *
     * @param data
     */
    public static void setAppClipboardObject(Object data) {
        ensureAppClipboard();
        appClipboard.setContents(new JVMObjectContent(data), null);
    }

    /**
     * 获取应用剪切板中存放的对象
     *
     * @return
     */
    public static Object getAppClipboardObject() {
        if (appClipboard == null) {
            return null;
        }
        try {
            return appClipboard.getContents(null).getTransferData(null);    // 下面已经处理
        } catch (Exception ignore) {
        }
        return null;
    }

    // 获取剪切板内容
    private static Object getDataFromClipboard(Clipboard clip, DataFlavor dataFlavor) {
        if (clip == null || !clip.isDataFlavorAvailable(dataFlavor)) {
            return null;
        }
        Object r = null;
        try {
            r = clip.getData(dataFlavor);
        } catch (Exception ignore) {
        }
        return r;
    }

    /**
     * 设置图片到给定剪切板
     *
     * @param clipboard
     * @param image
     */
    private static void setImageToClipboard(Clipboard clipboard, Image image) {
        if (clipboard == null) {
            return;
        }
        clipboard.setContents(new ImageContent(image), null);
    }


    // -----------
    private static void ensureAppClipboard() {
        if (appClipboard != null) {
            return;
        }
        synchronized (org.vacoor.nothing.ui.util.Clipboards.class) {
            if (appClipboard == null) {
                appClipboard = new Clipboard("App-Clipboard");
            }
        }
    }

    // 图像内容
    private static class ImageContent implements Transferable {
        private Image image;

        public ImageContent(Image image) {
            this.image = image;
        }

        @Override
        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[]{DataFlavor.imageFlavor};
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return DataFlavor.imageFlavor.match(flavor);
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            return isDataFlavorSupported(flavor) ? image : null;
        }
    }

    // JVM 对象内容
    private static class JVMObjectContent implements Transferable {
        private final DataFlavor objectDataFlavor;
        private final Object data;

        public JVMObjectContent(Object data) {
            String clazz = Object.class.getName();
            if (data != null && !data.getClass().isArray()) {
                clazz = data.getClass().getCanonicalName();
            }
            this.objectDataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + "; class=" + clazz, clazz);
            this.data = data;
        }

        @Override
        public DataFlavor[] getTransferDataFlavors() {
            try {
                return new DataFlavor[]{(DataFlavor) objectDataFlavor.clone()};
            } catch (CloneNotSupportedException e) {   // 应该不会出现
            }
            return new DataFlavor[0];
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return objectDataFlavor.match(flavor);
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            // return isDataFlavorSupported(flavor) ? data : null;
            // 即使不支持也返回
            return this.data;
        }
    }

    private Clipboards() {
    }
}